#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <error.h>
#include <pthread.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswresample/swresample.h>

#define BUFF_LEN 2048
#define PORT 1077

AVFormatContext *fmt_ctx = NULL;
AVCodecContext *cod_ctx = NULL;
AVCodec *cod = NULL;
AVPacket *packet = NULL;
AVFrame *frame = NULL;
struct SwrContext *convert_ctx;

int conn_fd;
void process_client();

#define MAX_AUDIO_FRAME_SIZE 192000

struct my_thread_struct{


};

/**
 * 接受adas设备码流并解析为pcm
 */
int main()
{
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(struct sockaddr_in)); //清零
    server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    server_addr.sin_port = htons(PORT);
    server_addr.sin_family = AF_INET;

    //绑定地址结构到套接字描述符
    if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind error\n");
        return -1;
    }

    if (listen(listen_fd, 20) < -1)
    {
        perror("listen error\n");
    }

    //=========================================ffmpeg prepare start ============================

    //注册所有的工具
    av_register_all();

    printf("step 2 ...........................\n");
    //分配一个avformat
    fmt_ctx = avformat_alloc_context();
    if (fmt_ctx == NULL)
        printf("alloc fail");

    printf("step 3 ...........................\n");

    cod = avcodec_find_decoder(AV_CODEC_ID_AAC);
    cod_ctx = avcodec_alloc_context3(cod);

    if (avcodec_open2(cod_ctx, cod, NULL) < 0)
        printf("can't open codec");

    //创建packet,用于存储解码前的数据
    packet = (AVPacket *)av_malloc(sizeof(AVPacket));

    //设置转码后输出相关参数
    //采样的布局方式
    uint64_t out_channel_layout = AV_CH_LAYOUT_MONO;
    //采样个数
    int out_nb_samples = 1024;
    //采样格式
    enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
    //采样率
    int out_sample_rate = 44100;
    //通道数
    int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
    printf("%d\n", out_channels);
    //创建buffer
    int buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, sample_fmt, 1);

    //注意要用av_malloc
    uint8_t *buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);

    //创建Frame，用于存储解码后的数据
    frame = av_frame_alloc();

    int got_picture;

    int64_t in_channel_layout = av_get_default_channel_layout(1);
    //打开转码器
    struct SwrContext *convert_ctx = swr_alloc();
    //设置转码参数
    convert_ctx = swr_alloc_set_opts(convert_ctx, out_channel_layout, sample_fmt, out_sample_rate,
                                     in_channel_layout, cod_ctx->sample_fmt, cod_ctx->sample_rate, 0, NULL);
    //初始化转码器
    swr_init(convert_ctx);

    //每次读取一帧，并转码,这里接受webscoket的数据
    av_init_packet(packet);

    //===========================================ffmpeg prepare end ===========================
    while (1)
    { //接受客户端连接
        socklen_t addrlen = sizeof(struct sockaddr);
        struct sockaddr_in clientaddr; //客户端地址结构

        conn_fd = accept(listen_fd, (struct sockaddr *)&clientaddr, &addrlen);

        if (conn_fd < 0)
        {
            perror("accept error");
            return -1;
        }
        printf("accept success\n");

        pthread_t pid;

        if (pthread_create(&pid, NULL, process_client, NULL) < 0)
        {
            printf("pthread create error\n");
        }
    }
    close(listen_fd);
}

void process_client()
{
    int sc = conn_fd;
    ssize_t size = 0;
    char buffer[BUFF_LEN];

    while (1)
    {
        memset(buffer, 0, BUFF_LEN);
        size = read(sc, buffer, BUFF_LEN);
        if (size > 0)
        {
            printf("fd is %d, got data: ", sc);
            for (size_t i = 0; i < size; i++)
            {
                printf("%x", buffer[i]);
            }
            printf("\n");

            int start_pos = strtok(buffer,0x7e);
            
            
            // ================================ start decode audio ===================
            //初始化工作完成，开启socket，准备解析数据
            int got_picture;
            char data[size];
            memcpy(data, buffer, size);
        

            buffer[15];
            //判断一下1078是否是分包，如果是分包，那么存储到线程变量，下一次访问的时候往线程变量里面放
            pthread_t sub_packet;
        
            pthread_setspecific(sub_packet,data);



            av_packet_from_data(packet, data, sizeof(data));
            //解码声音
            if (avcodec_decode_audio4(cod_ctx, frame, &got_picture, packet) < 0)
            {
                perror("decode error");
                return -1;
            }

            if (got_picture > 0)
            {
                //转码
                swr_convert(convert_ctx, &buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)frame->data, frame->nb_samples);

                printf("pts:%10lld\t packet size:%d\n", packet->pts, packet->size);
            }
            got_picture = 0;
            av_free_packet(packet);

            swr_free(&convert_ctx);

            // ================================ end decode audio ===================
        }
    }
}